#include "GlFireworksEffect.h"

#include "GlCamera.h"
#include "GlCommon.h"
#include "GlSize.h"
#include "GlSprite.h"
#include "Utility.h"

namespace GraphicLibrary
{
	//-----------------------------------------
	FireworksEffect::Particle::Particle(const Position pos)
		: mDirection(rand(Utility::Pi * 2.0f))
		, mSpeed(50.0f + rand(50.0f))
		, mDuration(1.5f + rand(0.5f))
		, mTime(0.0f)
		, mPos(pos)
		, mSprite(0)
	{
		mSprite = Sprite::Create("Fireworks/Particle");
		mSprite->move(mPos);
	}

	//-----------------------------------------
	FireworksEffect::Particle::~Particle()
	{
		delete mSprite;
	}

	//-----------------------------------------
	bool FireworksEffect::Particle::tick(const float deltaTime)
	{
		mTime += deltaTime;
		float perc = Utility::clamp(0.0f, 1.0f, mTime / mDuration);
		mSprite->move(shiftPos(mPos, mDirection, mTime * mSpeed));
		mSprite->setTransparency(tanh(perc));
		float scale = 1.0f + perc * 3.0f;
		scale *= 0.1;
		mSprite->setScale(Size(scale, scale));
		return mTime >= mDuration;
	}
}

namespace GraphicLibrary
{
	FireworksEffect::FireworksEffect(const float timeBetweenExplosions)
		: mTime(0.0f)
		, mTimeBetweenExplosions(timeBetweenExplosions)
	{
		createExplosion();
	}

	//-----------------------------------------
	FireworksEffect::~FireworksEffect()
	{
		for(ParticleArray::iterator i = mParticles.begin(); i != mParticles.end(); ++i)
			delete *i;
	}

	//-----------------------------------------
	bool FireworksEffect::tick(const float deltaTime)
	{
		mTime += deltaTime;
		if(mTime > mTimeBetweenExplosions)
		{
			createExplosion();
			mTime = 0.0f;
		}
		for(ParticleArray::iterator i = mParticles.begin(); i != mParticles.end(); ++i)
		{
			if(*i && (*i)->tick(deltaTime))
			{
				delete *i;
				*i = 0;
			}
		}
		while(!mParticles.empty() && !mParticles.front())
			mParticles.pop_front();
		return false;
	}

	//-----------------------------------------
	void FireworksEffect::createExplosion()
	{
		int particleCount = 20 + ::rand() % 20;
		Position pos;
		pos = Camera::GetSingleton()->projectScreenSpaceToGameSpace(rand(1.0f), rand(1.0f));
		for(int i = 0; i != particleCount; ++i)
			mParticles.push_back(new Particle(pos));
	}
}
